import webbrowser
from flask import Flask, render_template
import psutil
from threading import Thread
from time import sleep

app = Flask(__name__, static_folder='dist_vue/assets',
            template_folder='dist_vue')


@app.route('/', methods=['GET'])
def one_entry():
    return render_template('index.html')


def run_as_singleton():
    current_p = psutil.Process()
    current_p_name = current_p.name()
    current_p_pid = current_p.pid

    if current_p_name == 'python.exe':
        return

    for proc in psutil.process_iter(('pid', 'name')):
        p_info = proc.info

        if p_info.get('name') == current_p_name and p_info.get('pid') != current_p_pid:
            proc.kill()
            # 极端事例中, 在kill命令发出后尚未完成时get_available_port函数已产生新port
            sleep(0.5)


def get_available_port(candidate):
    port_generator = (i for i in range(2000, 10000))
    sconns = psutil.net_connections('tcp')
    while True:
        for conn in sconns:
            # if true, 端口占用
            if conn.status == 'LISTEN' and conn.laddr.port == candidate:
                break
        else:
            return candidate

        # 未try-catch
        # 极端情况下, next整个range都找不到可用port, 会报错
        candidate = next(port_generator)


def launch_browser(url):
    sleep(0.5)
    webbrowser.open(url)

    print('',
          ' *** Hi, friend from rongmei!',
          ' *** As long as this terminal window stay alive,',
          ' *** you can access the link below',
          ' *** through a Chromium-based web browser at any time.',
          f' *** running on {url}',
          '',
          sep='\n')


if __name__ == '__main__':
    run_as_singleton()
    host = '127.0.0.1'
    port = get_available_port(5000)
    url = f'http://{host}:{port}'

    Thread(target=launch_browser, args=(url,)).start()

    app.run(host, port)
